package util

import (
	"errors"
	"fmt"
	"github.com/gin-gonic/gin"
	"github.com/go-playground/validator/v10"
	"io"
)

// HoldContext 保持上下文
type HoldContext struct {
	Ctx    *gin.Context
	Errors error
}

var errorEOFTranceToSpace = errors.New(" ")

// AddError 错误记录器
func (h *HoldContext) AddError(err error) {
	if h.Errors == nil {
		h.Errors = err
	} else if err != nil {
		h.Errors = fmt.Errorf("%v; %w", h.Errors, err)
	}
}

// MakeContext 设置gin上下文
func (h *HoldContext) MakeContext(c *gin.Context) *HoldContext {
	h.Ctx = c
	return h
}

// BindVoJSON  入参绑定
func (h *HoldContext) BindVoJSON(vo any) *HoldContext {
	err := h.Ctx.BindJSON(vo)
	if err != nil {
		isFieldsRequiredError := isFieldsRequiredError(err)
		// 处理EOF错误
		if err == io.EOF {
			err = errorEOFTranceToSpace
			h.AddError(err)
		} else if isFieldsRequiredError != nil {
			//处理必填项err转义
			h.AddError(isFieldsRequiredError)
		} else {
			// 其他错误
			h.AddError(err)
		}
	}
	return h
}

// isFieldsRequiredError 判断是否是必填项错误
func isFieldsRequiredError(err error) error {
	var errorMsg []string
	var validationErrors validator.ValidationErrors
	if errors.As(err, &validationErrors) {
		for i, e := range validationErrors {
			camelErrorField := ToCamelCase(e.Field())
			errorMsg = append(errorMsg, fmt.Sprintf("Field %s is required", camelErrorField))
			if i < len(validationErrors)-1 {
				errorMsg[i] += " and"
			}
		}
		return fmt.Errorf("%v", errorMsg)
	}
	return nil
}
